<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>SuperMap iClient3D 测量工具</title>
    <!-- 引入Cesium和SuperMap iClient3D -->
    <script src="https://cdn.jsdelivr.net/npm/cesium@1.87/Build/Cesium/Cesium.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cesium@1.87/Build/Cesium/Widgets/widgets.css">
    <script src="https://iclient.supermap.io/web/libs/iclient3d/cesium/SuperMap3D.js"></script>
    
    <style>
        body {
            margin: 0;
            padding: 0;
        }
        #cesiumContainer {
            width: 100%;
            height: 100vh;
        }
        .toolbox {
            position: absolute;
            top: 20px;
            left: 20px;
            background: rgba(255, 255, 255, 0.9);
            padding: 10px;
            border-radius: 5px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
        }
        .toolbox button {
            margin: 5px;
            padding: 8px 12px;
            cursor: pointer;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 3px;
        }
        .toolbox button:hover {
            background: #0056b3;
        }
        .measure-label {
            color: #ff0000;
            font-weight: bold;
            white-space: nowrap;
        }
    </style>
</head>
<body>
    <div id="cesiumContainer"></div>
    <div class="toolbox">
        <button id="measureDistance">测距</button>
        <button id="measureArea">测面积</button>
        <button id="clearMeasure">清除</button>
    </div>

    <script>
        // 初始化场景
        const viewer = new Cesium.Viewer('cesiumContainer', {
            terrainProvider: Cesium.createWorldTerrain(),
            infoBox: false // 关闭默认信息框
        });

        // 测量状态变量
        let measuring = false; // 是否正在测量
        let measureType = null; // 测量类型：'distance' 或 'area'
        let points = []; // 测量点集合
        let entities = []; // 存储测量相关实体（线、面、标签）

        // 初始化工具按钮事件
        document.getElementById('measureDistance').addEventListener('click', () => {
            startMeasure('distance');
        });
        document.getElementById('measureArea').addEventListener('click', () => {
            startMeasure('area');
        });
        document.getElementById('clearMeasure').addEventListener('click', clearMeasure);

        // 开始测量
        function startMeasure(type) {
            // 清除之前的测量
            clearMeasure();
            measureType = type;
            measuring = true;
            points = [];
            
            // 创建鼠标事件处理器
            const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

            // 左键点击：添加测量点
            handler.setInputAction(movement => {
                if (!measuring) return;
                
                // 获取点击位置的坐标（考虑地形）
                const ray = viewer.camera.getPickRay(movement.position);
                const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
                if (!cartesian) return;

                points.push(cartesian);
                updateMeasureEntities(); // 更新测量图形
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

            // 右键点击：结束测量
            handler.setInputAction(() => {
                if (measuring) {
                    measuring = false;
                    handler.destroy(); // 销毁事件处理器
                }
            }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

            // 鼠标移动：实时更新临时线/面
            handler.setInputAction(movement => {
                if (!measuring || points.length === 0) return;
                
                // 获取鼠标当前位置坐标
                const ray = viewer.camera.getPickRay(movement.position);
                const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
                if (!cartesian) return;

                // 临时更新最后一个点，用于实时预览
                updateMeasureEntities(cartesian);
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        }

        // 更新测量实体（线/面/标签）
        function updateMeasureEntities(tempPoint) {
            // 清除之前的实体
            entities.forEach(entity => viewer.entities.remove(entity));
            entities = [];

            if (points.length < 1) return;

            // 复制点集合（添加临时点用于预览）
            const currentPoints = [...points];
            if (tempPoint) currentPoints.push(tempPoint);

            // 测距逻辑
            if (measureType === 'distance') {
                // 绘制测量线
                const lineEntity = viewer.entities.add({
                    polyline: {
                        positions: currentPoints,
                        width: 3,
                        material: Cesium.Color.RED,
                        clampToGround: true
                    }
                });
                entities.push(lineEntity);

                // 计算总距离并显示标签
                if (currentPoints.length >= 2) {
                    let totalDistance = 0;
                    for (let i = 0; i < currentPoints.length - 1; i++) {
                        totalDistance += Cesium.Cartesian3.distance(
                            currentPoints[i], 
                            currentPoints[i + 1]
                        );
                    }
                    // 格式化距离（米->千米）
                    const distanceText = totalDistance >= 1000 
                        ? `${(totalDistance / 1000).toFixed(2)} 千米` 
                        : `${totalDistance.toFixed(1)} 米`;

                    // 添加距离标签（显示在最后一个点）
                    const labelEntity = viewer.entities.add({
                        position: currentPoints[currentPoints.length - 1],
                        label: {
                            text: distanceText,
                            font: '16px sans-serif',
                            pixelOffset: new Cesium.Cartesian2(0, -20),
                            fillColor: Cesium.Color.RED,
                            outlineColor: Cesium.Color.WHITE,
                            outlineWidth: 2,
                            className: 'measure-label'
                        }
                    });
                    entities.push(labelEntity);
                }
            }

            // 测面积逻辑
            if (measureType === 'area' && currentPoints.length >= 3) {
                // 绘制测量面
                const polygonEntity = viewer.entities.add({
                    polygon: {
                        hierarchy: new Cesium.PolygonHierarchy(currentPoints),
                        material: Cesium.Color.RED.withAlpha(0.2),
                        outline: true,
                        outlineColor: Cesium.Color.RED,
                        clampToGround: true
                    }
                });
                entities.push(polygonEntity);

                // 计算球面面积
                const area = calculateArea(currentPoints);
                // 格式化面积（平方米->公顷->平方千米）
                let areaText;
                if (area >= 1000000) {
                    areaText = `${(area / 1000000).toFixed(2)} 平方千米`;
                } else if (area >= 10000) {
                    areaText = `${(area / 10000).toFixed(2)} 公顷`;
                } else {
                    areaText = `${area.toFixed(1)} 平方米`;
                }

                // 添加面积标签（显示在中心位置）
                const center = getPolygonCenter(currentPoints);
                const labelEntity = viewer.entities.add({
                    position: center,
                    label: {
                        text: areaText,
                        font: '16px sans-serif',
                        fillColor: Cesium.Color.RED,
                        outlineColor: Cesium.Color.WHITE,
                        outlineWidth: 2,
                        className: 'measure-label'
                    }
                });
                entities.push(labelEntity);
            }
        }

        // 计算多边形面积（基于WGS84椭球面）
        function calculateArea(points) {
            if (points.length < 3) return 0;
            
            const ellipsoid = viewer.scene.globe.ellipsoid;
            let area = 0;
            const cartographics = points.map(p => ellipsoid.cartesianToCartographic(p));

            // 使用球面多边形面积计算公式
            for (let i = 0; i < cartographics.length; i++) {
                const j = (i + 1) % cartographics.length;
                const ki = cartographics[i];
                const kj = cartographics[j];
                
                const a = ki.latitude;
                const b = kj.latitude;
                const c = Math.abs(ki.longitude - kj.longitude);
                
                area += 2 * Math.atan2(
                    Math.sin(c / 2) * (Math.sin(a) + Math.sin(b)),
                    Math.cos(a) + Math.cos(b) * Math.cos(c)
                );
            }
            
            return Math.abs(area) * (ellipsoid.maximumRadius **2);
        }

        // 获取多边形中心点（用于显示面积标签）
        function getPolygonCenter(points) {
            let x = 0, y = 0, z = 0;
            points.forEach(p => {
                x += p.x;
                y += p.y;
                z += p.z;
            });
            return new Cesium.Cartesian3(x / points.length, y / points.length, z / points.length);
        }

        // 清除测量结果
        function clearMeasure() {
            measuring = false;
            measureType = null;
            points = [];
            entities.forEach(entity => viewer.entities.remove(entity));
            entities = [];
        }
    </script>
</body>
</html>
